package data

import (
	"context"
	"gitee.com/jacktuotuo/coolcar/app/user/internal/biz"
	"gitee.com/jacktuotuo/coolcar/app/user/internal/conf"
	"gitee.com/jacktuotuo/coolcar/app/user/internal/data/token"
	"gitee.com/jacktuotuo/coolcar/app/user/internal/data/wechat"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/google/wire"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readpref"
	"time"
)

// ProviderSet is data providers.
var ProviderSet = wire.NewSet(NewData, NewUserRepo, NewMongo, NewOpenIdResolver, NewTokenGenerator)

// Data .
type Data struct {
	openIdResolver OpenIdResolver
	tokenGenerator TokenGenerator
	db             *mongo.Database
}

func NewMongo(conf *conf.Data) *mongo.Database {
	ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	client, err := mongo.Connect(ctx, options.Client().ApplyURI(conf.Mongodb.Uri))
	if err != nil {
		panic(err)
	}
	err = client.Ping(ctx, readpref.Primary())
	if err != nil {
		panic(err)
	}
	return client.Database(conf.Mongodb.Database)
}

func NewOpenIdResolver(conf *conf.Data) OpenIdResolver {
	return wechat.NewOpenIdResolver(conf.Wechat.GetAppid(), conf.Wechat.GetSecret())
}

func NewTokenGenerator(conf *conf.Data) TokenGenerator {
	return token.NewJwtTokenGenerator(conf.Auth.GetPrivateKeyPath(), conf.Auth.GetExpiresTime(), conf.Auth.GetIssue())
}

// NewUserRepo .
func NewUserRepo(data *Data, logger log.Logger) biz.UserRepo {
	return &userRepo{
		data:      data,
		userColl:  data.db.Collection("account"),
		log:       log.NewHelper(logger),
		resolver:  data.openIdResolver,
		generator: data.tokenGenerator,
		newObjID:  primitive.NewObjectID,
	}
}

// NewData .
func NewData(database *mongo.Database, resolver OpenIdResolver, generator TokenGenerator, logger log.Logger) (*Data, func(), error) {
	cleanup := func() {
		log.NewHelper(logger).Info("closing the data resources")
	}
	return &Data{
		openIdResolver: resolver,
		tokenGenerator: generator,
		db:             database,
	}, cleanup, nil
}
